#include "wiota_flashing.h"
#include "config_api.h"
#include "drv_gpio.h"
#include "extern_flash_read.h"
#include "manager_crc.h"
#include "slave_uc8x88.h"
#include "slave_uc8x88_cfg.h"
#include "sync_assistant.h"
#include "uc_wiota_api.h"
#include "watchdog_app.h"
#include <rtdevice.h>
#include <rtthread.h>
#include <stdio.h>
#ifdef UC_USING_AT_COM
#include "ap_at_com.h"
#elif defined(UC_USING_SPI_COM)
#include "ap_spi_com.h"
#endif

#define DBG_ENABLE
#define DBG_SECTION_NAME "flashing"
#include "uc_log.h"

#define SPI_SWITCH_PIN GET_PIN(B, 6)
#define AP_SPI_MAX_HZ (10 * 1000 * 1000)

#define DATA_HEAD "UC"
#define SYNC_DATA_HEAD_SIZE 2
#define TEMP_TO_DCXO_SIZE 32
#define RAMP_DAC_POWER_MAX_NUM 42
#define USER_INFO_SIZE 256

// 同步助手动态信息地址
#define SYNC_DYNAMICS_INFO_ADDR 0x30EB00

/**
 * @brief uboot配置信息结构体
 *
 */
typedef struct
{
    unsigned char baud_flag;
    unsigned char mode;
    unsigned char uart_flag;
    unsigned char log_flag;
    unsigned char select_flag;
    unsigned char wait_sec;
    unsigned char reserved[2];
    unsigned int baud_rate;
    unsigned int file_size;
    unsigned int record_address;
    unsigned char version[4];
    unsigned int bin_partition_size;
    unsigned int reserved_partition_size;
    unsigned int ota_partition_size;
} uboot_record_data;

/**
 * @brief 设备信息结构体
 *
 */
typedef struct
{
    unsigned char userid_info[8];
    unsigned char name_info[16];
    unsigned char dev_serial_info[16];
    unsigned char soft_ver_info[16];
    unsigned char manufacture_name[16];
    unsigned char hardware_ver_info[16];
    unsigned char is_oscillator;
    unsigned char auto_connect;
    unsigned char dtu_enable;
    unsigned char dtu_at_show;
    unsigned short dtu_time_out;
    unsigned short dtu_wait;
    unsigned char dtu_exit[8];
    unsigned int at_baud_rate;
    unsigned char store_pin;
    unsigned char store_width;
    unsigned char wake_out_pin;
    unsigned char wake_out_width;
    unsigned char na[16];
} device_info_t;

/**
 * @brief 同步助手子网配置
 *
 */
typedef struct
{
    unsigned char reserved0;
    unsigned char id_len;
    unsigned char pp;
    unsigned char symbol_length;
    unsigned char pz;
    unsigned char bt_value;
    unsigned char band_width;
    unsigned char spectrum_idx;
    unsigned short freq_idx;
    unsigned char reserved1[2];
    unsigned int subsystem_id;
    unsigned short freq_list[16];
    unsigned char na[16];
} sub_system_config_ex_t;

/**
 * @brief 射频静态数据结构体
 *
 */
typedef struct
{
    signed char temp_list[TEMP_TO_DCXO_SIZE];
    unsigned char dcx0_list[TEMP_TO_DCXO_SIZE];
    signed char pow_min;
    unsigned char pow_num;
    unsigned char tx_mode;
    signed char tx_pow;
    unsigned short ramp_list[RAMP_DAC_POWER_MAX_NUM];
    unsigned char na[8];
} rf_static_info_t;

/**
 * @brief 射频动态使用信息结构体
 *
 */
typedef struct
{
    unsigned char dcxo;
    unsigned char agc_idx;
    unsigned short reserved;
    signed char temp_adjust;
    unsigned char dcxo_dir;
    unsigned char dcxo_adjust;
    unsigned char tcxo_dir;
    unsigned int tcxo_offset;
} rf_dynamic_used_t;

/**
 * @brief 低功耗paging rx配置结构体
 *
 */
typedef struct
{
    unsigned char reserved;
    unsigned char spectrum_idx;
    unsigned char band_width;
    unsigned char symbol_length;
    unsigned char lpm_nlen;
    unsigned char lpm_utimes;
    unsigned char threshold;
    unsigned char extra_flag;
    unsigned short awake_id;
    unsigned short freq;
    unsigned int detect_period;
    unsigned int extra_period;
    unsigned char reserved1;
    unsigned char period_multiple;
    unsigned short awaken_id_another;
} uc_lpm_rx_cfg_ex_t;

/**
 * @brief 低功耗paging tx配置结构体
 *
 */
typedef struct
{
    unsigned char reserved;
    unsigned char spectrum_idx;
    unsigned char band_width;
    unsigned char symbol_length;
    unsigned short awaken_id;
    unsigned short freq;
    unsigned int send_time;
} uc_lpm_tx_cfg_ex_t;

/**
 * @brief 射频动态配置结构体
 *
 */
typedef struct
{
    rf_dynamic_used_t rf_used;
    uc_lpm_rx_cfg_ex_t lpm_rx_cfg;
    uc_lpm_tx_cfg_ex_t lpm_tx_cfg;
    unsigned char factory_ctrl;
    unsigned char na[15];
} rf_dynamic_info_t;

/**
 * @brief 同步助手有效静态数据结构体
 *
 */
typedef struct
{
    uboot_record_data record_data;
    device_info_t device_info;
    sub_system_config_ex_t network_info;
    rf_static_info_t rf_static_info;
    rf_dynamic_info_t rf_dynamic_info;
    unsigned char user_info[256];
} sync_static_t;

/**
 * @brief 同步助手静态数据结构体
 *
 */
typedef struct
{
    char data_head[SYNC_DATA_HEAD_SIZE];
    short version;
    unsigned int total_size;
    unsigned int used_size;
    unsigned int readonly_size;
    unsigned int crc32_value;
    uboot_record_data record_data;
    device_info_t device_info;
    sub_system_config_ex_t network_info;
    rf_static_info_t rf_static_info;
    rf_dynamic_info_t rf_dynamic_info;
    sync_cfg_t sync_cfg;
    unsigned char user_info[216]; // 256 - sizeof(sync_cfg_t)
} sync_static_data_t;

/**
 * @brief 同步助手静态数据本地全局变量
 *
 */
sync_static_data_t g_sync_static_data = {
    .data_head = DATA_HEAD,
    .version = 1,
    .total_size = sizeof(sync_static_t) + 20,
    .used_size = sizeof(sync_static_t),
    .readonly_size = 0,
    .crc32_value = 0,
    .record_data = {
        .baud_flag = 2,
        .mode = 0x60,
        .uart_flag = 1,
        .log_flag = 0,
        .select_flag = 1,
        .wait_sec = 0,
        .reserved = {0, 0},
        .baud_rate = 115200,
        .file_size = 0,
        .record_address = 0,
        .version = "v1.0",
        .bin_partition_size = 0x4B000,
        .reserved_partition_size = 0x1C000,
        .ota_partition_size = 0x17000,
    },
    .device_info = {
        .userid_info = {0x4c, 0xb5, 0xc8, 0x63, 0, 0, 0, 0},
        .name_info = "8288",
        .dev_serial_info = "123456",
        .soft_ver_info = "v4.0_async",
        .manufacture_name = "ucchip",
        .hardware_ver_info = "v1.0",
        .is_oscillator = 0,
        .auto_connect = 0,
        .dtu_enable = 0,
        .dtu_at_show = 0,
        .dtu_time_out = 0,
        .dtu_wait = 0,
        .dtu_exit = {0},
        .at_baud_rate = 115200,
        .store_pin = 0,
        .store_width = 0,
        .wake_out_pin = 0,
        .wake_out_width = 0,
        .na = {0},
    },
    .network_info = {
        .reserved0 = 0,
        .id_len = 1,
        .pp = 1,
        .symbol_length = 3,
        .pz = 8,
        .bt_value = 1,
        .band_width = 4,
        .spectrum_idx = 3,
        .freq_idx = 160,
        .reserved1 = {0},
        .subsystem_id = 0x21456981,
        .freq_list = {125, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF},
        .na = {0},
    },
    .rf_static_info = {
        .temp_list = {-49, -48, -45, -41, -38, -35, -31, -28, -25, -21, -15, 3, 10, 17, 25, 34, 42, 51, 61, 68, 72, 76, 79, 81, 83, 85, 87, 89, 90, 92, 93, 94},
        .dcx0_list = {38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 29, 30, 31, 32, 33, 34, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21},
        .pow_min = -18,
        .pow_num = 41,
        .tx_mode = 3,
        .tx_pow = 10,
        .ramp_list = {0, 5, 7, 10, 12, 15, 18, 21, 25, 28, 33, 38, 43, 49, 55, 62, 71, 80, 90, 102, 116, 130, 146, 165, 185, 209, 234, 262, 289, 319, 353, 392, 435, 484, 539, 601, 671, 751, 842, 950, 1023, 1023},
        .na = {0},
    },
    .rf_dynamic_info = {
        .rf_used = {
            .dcxo = 32,
            .agc_idx = 15,
            .reserved = 0,
            .temp_adjust = 0,
            .dcxo_dir = 0,
            .dcxo_adjust = 0,
            .tcxo_dir = 0,
            .tcxo_offset = 0,
        },
        .lpm_rx_cfg = {
            .reserved = 0,
            .spectrum_idx = 3,
            .band_width = 1,
            .symbol_length = 1,
            .lpm_nlen = 4,
            .lpm_utimes = 2,
            .threshold = 10,
            .extra_flag = 0,
            .awake_id = 30,
            .freq = 160,
            .detect_period = 1000,
            .extra_period = 1000,
            .reserved1 = 0,
            .period_multiple = 0,
            .awaken_id_another = 0,
        },
        .lpm_tx_cfg = {
            .reserved = 0,
            .spectrum_idx = 3,
            .band_width = 1,
            .symbol_length = 1,
            .awaken_id = 30,
            .freq = 160,
            .send_time = 1000,
        },
        .factory_ctrl = 0,
        .na = {0},
    },
    .user_info = {0},
};

/**
 * @brief SPI2 slaver切换，PB6高电平控制同步助手，低电平控制AP
 *
 * @param chip_index         芯片下标
 */
static void wiota_spi_slaver_switch(unsigned char chip_index)
{
    char *hw_version = uc_static_get_gateway_base_cfg()->hardware_version;

    if (0 == rt_strcmp(hw_version, CFG_HARDWARE_VERSION_V1_3))
    {
        rt_pin_mode(SPI_SWITCH_PIN, PIN_MODE_OUTPUT);
        if (chip_index == AP_CHIP_INDEX)
        {
            rt_pin_write(SPI_SWITCH_PIN, PIN_LOW);
        }
        else if (chip_index == SYNC_ASSISTANT_CHIP_INDEX)
        {
            rt_pin_write(SPI_SWITCH_PIN, PIN_HIGH);
        }
        TRACE_D("switch spi slaver to chip_index %d", chip_index);
    }
}

sync_dynamics_info_t *wiota_get_sync_dynamics_info(void)
{
    sync_dynamics_info_t *sync_info = rt_malloc(sizeof(sync_dynamics_info_t));
    RT_ASSERT(sync_info);
    rt_memset(sync_info, 0, sizeof(sync_dynamics_info_t));

    wiota_spi_slaver_switch(SYNC_ASSISTANT_CHIP_INDEX);
    if (0 != slave_uc8x88_mem_read_data(SYNC_ASSISTANT_CHIP_INDEX, SYNC_DYNAMICS_INFO_ADDR, (unsigned char *)sync_info, sizeof(sync_dynamics_info_t)))
    {
        rt_free(sync_info);
        wiota_spi_slaver_switch(AP_CHIP_INDEX);
        return RT_NULL;
    }
    wiota_spi_slaver_switch(AP_CHIP_INDEX);

    if (sync_info->neighbor_num > GW_MAX_NEIGHBOR_NUM)
    {
        sync_info->neighbor_num = GW_MAX_NEIGHBOR_NUM;
        TRACE_W("neighbor_num %d is too large, set to %d", sync_info->neighbor_num, GW_MAX_NEIGHBOR_NUM);
    }
    return sync_info;
}

/**
 * @brief 将网关静态数据更新到本地，并计算CRC32
 *
 */
static void wiota_update_sync_static_data(void)
{
    sync_cfg_t *sync_cfg = uc_static_get_sync_cfg();

    // 将网关静态数据更新到本地
    rt_memcpy(&g_sync_static_data.sync_cfg, sync_cfg, sizeof(sync_cfg_t));
    // 计算crc32
    g_sync_static_data.crc32_value = crc32_calc((unsigned char *)&g_sync_static_data.record_data, g_sync_static_data.used_size);
    TRACE_I("update sync static data, crc32_value 0x%x", g_sync_static_data.crc32_value);
}

/**
 * @brief 根据规则找到静态数据起始地址
 *
 * @param data      静态数据
 * @param data_size 静态数据大小
 * @param crc32     静态数据crc32校验值，用于和本地数据比较
 * @return int      起始地址，-1表示未找到
 */
static int wiota_find_sync_static_data(unsigned char *data, int data_size, unsigned int *crc32)
{
    char data_head[SYNC_DATA_HEAD_SIZE] = {0};
    int start_addr = -1;
    int data_len = UC8288_STATIC_DATA_SIZE - data_size;

    for (int i = 0; i < data_len; i += 4)
    {
        rt_memcpy(data_head, &data[i], SYNC_DATA_HEAD_SIZE);

        if (0 == rt_memcmp(data_head, DATA_HEAD, SYNC_DATA_HEAD_SIZE))
        {
            unsigned int used_size = *(unsigned int *)(&data[i] + 8);
            unsigned int crc32_value = *(unsigned int *)(&data[i] + 16);
            unsigned int calc_crc = crc32_calc((unsigned char *)(&data[i] + 20), used_size);

            if (used_size == g_sync_static_data.used_size && crc32_value == calc_crc)
            {
                start_addr = i;
                *crc32 = calc_crc;
                TRACE_I("find sync static start_addr 0x%x, total_size %d, used_size %d, crc32_value 0x%x",
                        start_addr, g_sync_static_data.total_size, used_size, crc32_value);
            }
            break;
        }
    }

    return start_addr;
}

/**
 * @brief 同步助手静态数据初始化，从flash读取，比较和本地是否相同，不同则重刷，相同则不用重刷
 *
 */
static void wiota_sync_assistant_static_data_init(void)
{
    unsigned char *read_data = RT_NULL;
    int start_addr = 0;
    int is_flash_static = 0;
    unsigned int crc32_value = 0;

    // crc初始化，用户数据crc校验计算
    crc32_init();

    // 从网关静态数据更新到本地
    wiota_update_sync_static_data();
    // 读取同步助手静态数据
    read_data = rt_malloc(UC8288_STATIC_DATA_SIZE);
    RT_ASSERT(read_data);
    rt_memset(read_data, 0, UC8288_STATIC_DATA_SIZE);
    slave_uc8x88_flash_read_data(SYNC_ASSISTANT_CHIP_INDEX, BACKUP_DATA_ADDR, read_data, UC8288_STATIC_DATA_SIZE);
    // 大小端转换
    bswap32_buf(read_data, UC8288_STATIC_DATA_SIZE);

    // 查找是否存在静态数据
    start_addr = wiota_find_sync_static_data(read_data, g_sync_static_data.total_size, &crc32_value);
    if (start_addr != -1)
    {
        // 存在，比较和本地是否相同
        if (crc32_value == g_sync_static_data.crc32_value)
        {
            // 相同，不用重刷
            TRACE_I("flash static data match");
        }
        else
        {
            // 不同，重刷
            is_flash_static = 1;
            TRACE_W("flash static data not match, reflash now!");
        }
    }
    else
    {
        // 不存在，重刷
        is_flash_static = 1;
        TRACE_W("flash static data not exist, reflash now!");
    }

    if (is_flash_static)
    {
        // 写入时把g_sync_static_data进行大小端转换后写入
        rt_memset(read_data, 0, UC8288_STATIC_DATA_SIZE);
        rt_memcpy(read_data, &g_sync_static_data, g_sync_static_data.total_size);
        bswap32_buf(read_data, UC8288_STATIC_DATA_SIZE);

        // 先擦除
        slave_uc8x88_flash_erase(SYNC_ASSISTANT_CHIP_INDEX, BACKUP_DATA_ADDR, UC8288_STATIC_DATA_SIZE);
        // 数据区
        if (0 == slave_uc8x88_flash_write_data(SYNC_ASSISTANT_CHIP_INDEX,
                                               BACKUP_DATA_ADDR,
                                               read_data,
                                               g_sync_static_data.total_size,
                                               1))
        {
            TRACE_I("flash static data write ok");
        }
        else
        {
            TRACE_E("flash static data write fail");
        }
    }

    rt_free(read_data);
}

/**
 * @brief 刷机初始化，SPI和flash
 *
 * @param chip_index         芯片下标
 * @param expected_chip_type 期望的芯片类型UC8088或UC8288
 * @param expected_flash_id  期望的flash id
 * @return int               0表示成功，非0表示失败
 */
static int wiota_flashing_init(unsigned char chip_index, slave_uc8x88_chip_type_e expected_chip_type, unsigned short expected_flash_id)
{
    slave_uc8x88_chip_type_e actual_chip_type = CHIP_TYPE_UNKNOWN;
    unsigned short actual_flash_id = 0;

    slave_uc8x88_init(chip_index);
    slave_uc8x88_flash_init(chip_index);

    actual_chip_type = slave_uc8x88_get_chip_type(chip_index);
    actual_flash_id = slave_uc8x88_flash_read_id(chip_index);
    TRACE_I("chip_index %d chip_type %d, flash_id 0x%x", chip_index, actual_chip_type, actual_flash_id);

    if (expected_chip_type == actual_chip_type && expected_flash_id == actual_flash_id)
    {
        return RT_EOK;
    }
    TRACE_E("chip_index %d flashing init fail", chip_index);

    return RT_ERROR;
}

/**
 * @brief 检查是否需要重新刷机，对比镜像时间戳是否相同，不同则表示需要重刷
 *
 * @param chip_index     芯片下标
 * @param timestamp_addr 镜像时间戳地址
 * @param new_timestamp  本地镜像的时间戳
 * @return int           1表示需要重刷，0表示不需要
 */
static int wiota_flashing_check_if_require_reflash(unsigned char chip_index, unsigned int timestamp_addr, unsigned int new_timestamp)
{
    unsigned int old_timestamp = 0;
    int is_require = 0;

    slave_uc8x88_flash_read_data(chip_index, timestamp_addr, (unsigned char *)&old_timestamp, 4);
    TRACE_I("chip_index %d new_timestamp %u, old_timestamp %u", chip_index, new_timestamp, old_timestamp);

    if (new_timestamp != old_timestamp)
    {
        TRACE_I("chip_index %d require to reflash", chip_index);
        is_require = 1;
    }
    else
    {
        TRACE_I("chip_index %d not require to reflash", chip_index);
    }

    return is_require;
}

/**
 * @brief 通过SPI烧录镜像
 *
 * @param chip_index     芯片下标
 * @param erase_size     烧写时擦除的flash大小
 * @param bin            镜像地址
 * @param bin_size       镜像大小
 * @param timestamp_addr 镜像时间戳地址
 * @param timestamp      镜像时间戳
 * @return int           0表示成功，非0表示失败
 */
static int wiota_flashing_bin(unsigned char chip_index,
                              unsigned int erase_size,
                              unsigned char *bin, unsigned int bin_size,
                              unsigned int timestamp_addr, unsigned int timestamp)
{
    int ret = -RT_ERROR;
    int offset = 0;
    int write_size = 0;
    unsigned int left_size = 0;
    unsigned int last_flashing_rate = 0xFFFFFFFF;
    unsigned int cur_flashing_rate = 0;

    TRACE_I("chip_index %d flashing start, wait...", chip_index);
    slave_uc8x88_flash_erase(chip_index, 0, erase_size);
    TRACE_I("chip_index %d flashing erase ok", chip_index);

    for (offset = 0; offset < bin_size; offset += FLASHING_SECTOR_SIZE)
    {
        left_size = bin_size - offset;
        write_size = left_size < FLASHING_SECTOR_SIZE ? left_size : FLASHING_SECTOR_SIZE;
        if (write_size > 0)
        {
            cur_flashing_rate = offset * 100 / bin_size;
            if (last_flashing_rate != cur_flashing_rate)
            {
                TRACE_I("chip_index %d flashing %d%%", chip_index, cur_flashing_rate);
            }
            last_flashing_rate = cur_flashing_rate;
            ret = slave_uc8x88_flash_write_data(chip_index, offset, &bin[offset], write_size, 1);
            if (0 != ret)
            {
                return ret;
            }
        }
        // 防止看门狗重启
        rt_thread_mdelay(1);
    }

    return slave_uc8x88_flash_write_data(chip_index, timestamp_addr, (unsigned char *)&timestamp, 4, 1);
}

/**
 * @brief 根据芯片下标烧写对应镜像
 *
 * @param chip_index 芯片下标
 * @param chip_type  芯片类型
 * @param flash_id   flash id
 * @param erase_size 烧写时擦除的flash大小
 * @param bin        镜像地址
 * @param bin_size   镜像大小
 * @param timestamp  镜像时间戳
 * @return int       0表示成功，非0表示失败
 */
static int wiota_flashing_by_chip_index(unsigned char chip_index,
                                        slave_uc8x88_chip_type_e chip_type, unsigned short flash_id,
                                        unsigned int erase_size,
                                        unsigned char *bin, unsigned int bin_size,
                                        unsigned int timestamp)
{
    int ret = 0;
    unsigned int timestamp_addr = RT_ALIGN(bin_size, 256);

    if (RT_EOK != wiota_flashing_init(chip_index, chip_type, flash_id))
    {
        return -1;
    }

    // 烧写同步助手静态数据
    if (chip_index == SYNC_ASSISTANT_CHIP_INDEX)
    {
        wiota_sync_assistant_static_data_init();
    }

    if (wiota_flashing_check_if_require_reflash(chip_index, timestamp_addr, timestamp))
    {
        ret = wiota_flashing_bin(chip_index,
                                 erase_size,
                                 bin, bin_size,
                                 timestamp_addr, timestamp);
        if (0 != ret)
        {
            TRACE_E("chip_index %d flashing fail", chip_index);
        }
        else
        {
            TRACE_I("chip_index %d flashing suc", chip_index);
        }
    }
    slave_uc8x88_flash_start_app(chip_index);

    return ret;
}

static int wiota_read_bin_from_extern_flash(unsigned char chip_index,
                                            unsigned int offset,
                                            unsigned char *bin, unsigned int read_size)
{
    if (chip_index == SYNC_ASSISTANT_CHIP_INDEX)
    {
        return read_200t_param(offset, bin, read_size);
    }
    else
    {
        return read_ap_param(offset, bin, read_size);
    }
}

time_t get_timestamp_from_date_time(void)
{
    // 获取编译日期和时间
    const char *date_string = __DATE__; // 示例： "Oct 24 2023"
    const char *time_string = __TIME__; // 示例： "14:30:00"

    // 创建一个字符串用于组合日期和时间
    char datetime_string[100];
    rt_snprintf(datetime_string, sizeof(datetime_string), "%s %s", date_string, time_string);

    // 解析字符串为时间结构
    struct tm tm;
    rt_memset(&tm, 0, sizeof(struct tm)); // 清零
    sscanf(datetime_string, "%3s %d %d %d:%d:%d",
           &tm.tm_mon, &tm.tm_mday, &tm.tm_year,
           &tm.tm_hour, &tm.tm_min, &tm.tm_sec);

    // 注意：tm_year 是从1900年开始的
    tm.tm_year -= 1900;
    // 注意：tm_mon 是从0开始的
    if (rt_strcmp(date_string, "Jan") == 0)
        tm.tm_mon = 0;
    else if (rt_strcmp(date_string, "Feb") == 0)
        tm.tm_mon = 1;
    else if (rt_strcmp(date_string, "Mar") == 0)
        tm.tm_mon = 2;
    else if (rt_strcmp(date_string, "Apr") == 0)
        tm.tm_mon = 3;
    else if (rt_strcmp(date_string, "May") == 0)
        tm.tm_mon = 4;
    else if (rt_strcmp(date_string, "Jun") == 0)
        tm.tm_mon = 5;
    else if (rt_strcmp(date_string, "Jul") == 0)
        tm.tm_mon = 6;
    else if (rt_strcmp(date_string, "Aug") == 0)
        tm.tm_mon = 7;
    else if (rt_strcmp(date_string, "Sep") == 0)
        tm.tm_mon = 8;
    else if (rt_strcmp(date_string, "Oct") == 0)
        tm.tm_mon = 9;
    else if (rt_strcmp(date_string, "Nov") == 0)
        tm.tm_mon = 10;
    else if (rt_strcmp(date_string, "Dec") == 0)
        tm.tm_mon = 11;

    // 将 tm 转换为时间戳
    time_t timestamp = mktime(&tm);

    return timestamp;
}

static int wiota_flashing_extern_flash_bin(unsigned char chip_index,
                                           slave_uc8x88_chip_type_e chip_type, unsigned short flash_id,
                                           unsigned int erase_size)
{
    if (RT_EOK != wiota_flashing_init(chip_index, chip_type, flash_id))
    {
        return -1;
    }

    int ret = -RT_ERROR;
    int offset = 0;
    int write_size = 0;
    unsigned int left_size = 0;
    unsigned int last_flashing_rate = 0xFFFFFFFF;
    unsigned int cur_flashing_rate = 0;
    unsigned int bin_size = (chip_index == SYNC_ASSISTANT_CHIP_INDEX ? U200T_PARAMENT_SIZE : AP_PARAMENT_SIZE);
    time_t timestamp = get_timestamp_from_date_time();

    unsigned int timestamp_addr = RT_ALIGN(bin_size, 256);
    if (0 == wiota_flashing_check_if_require_reflash(chip_index, timestamp_addr, timestamp))
    {
        return 0;
    }

    TRACE_I("chip_index %d flashing start, wait...", chip_index);
    slave_uc8x88_flash_erase(chip_index, 0, erase_size);
    TRACE_I("chip_index %d flashing erase ok", chip_index);

    unsigned char *bin = rt_malloc(FLASHING_SECTOR_SIZE);
    RT_ASSERT(bin);

    for (offset = 0; offset < bin_size; offset += FLASHING_SECTOR_SIZE)
    {
        left_size = bin_size - offset;
        write_size = left_size < FLASHING_SECTOR_SIZE ? left_size : FLASHING_SECTOR_SIZE;
        if (write_size > 0)
        {
            cur_flashing_rate = offset * 100 / bin_size;
            if (last_flashing_rate != cur_flashing_rate)
            {
                TRACE_I("chip_index %d flashing %d%%", chip_index, cur_flashing_rate);
            }
            last_flashing_rate = cur_flashing_rate;

            rt_memset(bin, 0, FLASHING_SECTOR_SIZE);
            if (0 != wiota_read_bin_from_extern_flash(chip_index, offset, bin, write_size))
            {
                TRACE_W("read bin from extern flash fail, offset %d, size %d", offset, write_size);
                return -RT_ERROR;
            }
            ret = slave_uc8x88_flash_write_data(chip_index, offset, bin, write_size, 1);
            if (0 != ret)
            {
                TRACE_W("write bin to flash fail, offset %d, size %d", offset, write_size);
                return ret;
            }
        }
        // 防止看门狗重启
        rt_thread_mdelay(1);
    }
    slave_uc8x88_flash_write_data(chip_index, timestamp_addr, (unsigned char *)&timestamp, 4, 1);
    slave_uc8x88_flash_start_app(chip_index);

    return 0;
}

/**
 * @brief 刷写AP射频测试模式镜像
 *
 * @return int 0表示成功，非0表示失败
 */
int wiota_flashing_ap_rf_test_bin(void)
{
    // 使能AP电源
    uc_wiota_power_on();
    // 必要延迟，等待模组上电启动
    rt_thread_mdelay(100);
    uc_wiota_reboot();
    rt_thread_mdelay(500);
    // spi slaver 切换到AP
    wiota_spi_slaver_switch(AP_CHIP_INDEX);
    int ap_res = wiota_flashing_extern_flash_bin(AP_CHIP_INDEX,
                                                 CHIP_TYPE_UC8088,
                                                 UC8088_FLASH_ID,
                                                 UC8088_ERASE_SIZE);
    slave_uc8x88_spi_config(AP_CHIP_INDEX, AP_SPI_MAX_HZ);
    TRACE_I("chip_index 0 config spi max_hz to %d M", AP_SPI_MAX_HZ / (1000 * 1000));
    wiota_spi_slaver_switch(SYNC_ASSISTANT_CHIP_INDEX); // rf 测试直接将spi cs切到同步助手
    uc_wiota_reboot();
    rt_thread_mdelay(500);

    return ap_res;
}

/**
 * @brief 刷写同步助手射频测试模式镜像
 *
 * @return int 0表示成功，非0表示失败
 */
int wiota_flashing_sync_rf_test_bin(void)
{
    // 使能同步助手电源
    uc_wiota_sync_assistant_power_on();
    rt_thread_mdelay(100);
    uc_wiota_sync_assistant_reboot();
    rt_thread_mdelay(500);
    // spi slaver 切换到同步助手
    wiota_spi_slaver_switch(SYNC_ASSISTANT_CHIP_INDEX);
    int sync_res = wiota_flashing_extern_flash_bin(SYNC_ASSISTANT_CHIP_INDEX,
                                                   CHIP_TYPE_UC8288,
                                                   UC8288_FLASH_ID,
                                                   UC8288_ERASE_SIZE);

    uc_wiota_sync_assistant_reboot();
    rt_thread_mdelay(500);

    return sync_res;
}

/**
 * @brief 刷写AP正常模式镜像
 *
 * @return int 0表示成功，非0表示失败
 */
int wiota_flashing_ap_normal_bin(void)
{
    unsigned char *ap = RT_NULL;
    unsigned int ap_len = 0;
    unsigned int ap_timestamp = 0;
    int ap_res = 0xff;

#ifdef UC_USING_AT_COM
    ap = (unsigned char *)ap_at_com;
    ap_len = ap_at_com_len;
    ap_timestamp = ap_at_com_timestamp;
#elif defined(UC_USING_SPI_COM)
    ap = (unsigned char *)ap_spi_com;
    ap_len = ap_spi_com_len;
    ap_timestamp = ap_spi_com_timestamp;
#endif

#ifdef UC_GATEWAY_HARDWARE_V1_0
    // 使能AP电源
    uc_wiota_power_on();
    // 必要延迟，等待模组上电启动
    rt_thread_mdelay(300);
    ap_res = wiota_flashing_by_chip_index(AP_CHIP_INDEX,
                                          CHIP_TYPE_UC8088,
                                          UC8088_FLASH_ID,
                                          UC8088_ERASE_SIZE,
                                          ap, ap_len,
                                          ap_timestamp);
#else
    // 使能AP电源
    uc_wiota_power_on();
    // 必要延迟，等待模组上电启动
    rt_thread_mdelay(100);
    uc_wiota_reboot(); // 增加复位
    rt_thread_mdelay(500);

    // spi slaver 切换到AP
    wiota_spi_slaver_switch(AP_CHIP_INDEX);
    ap_res = wiota_flashing_by_chip_index(AP_CHIP_INDEX,
                                          CHIP_TYPE_UC8088,
                                          UC8088_FLASH_ID,
                                          UC8088_ERASE_SIZE,
                                          ap, ap_len,
                                          ap_timestamp);
    slave_uc8x88_spi_config(AP_CHIP_INDEX, AP_SPI_MAX_HZ);
    TRACE_I("chip_index 0 config spi max_hz to %d M", AP_SPI_MAX_HZ / (1000 * 1000));
#endif
    // 如果为AT通信，刷完程序将slaver切换回同步助手，保证不影响接烧录器
#ifdef UC_USING_AT_COM
    wiota_spi_slaver_switch(SYNC_ASSISTANT_CHIP_INDEX);
#endif
    uc_wiota_reboot();
    rt_thread_mdelay(500);

    return ap_res;
}

/**
 * @brief 刷写同步助手正常模式镜像
 *
 * @return int 0表示成功，非0表示失败
 */
int wiota_flashing_sync_normal_bin(void)
{
    int sync_res = 0xff;
#ifdef UC_GATEWAY_HARDWARE_V1_0
    // 关闭AP电源
    uc_wiota_power_off();
    // 使能同步助手电源
    uc_wiota_sync_assistant_power_on();
    // 必要延迟，等待模组上电启动
    rt_thread_mdelay(300);
    sync_res = wiota_flashing_by_chip_index(SYNC_ASSISTANT_CHIP_INDEX,
                                            CHIP_TYPE_UC8288,
                                            UC8288_FLASH_ID,
                                            UC8288_ERASE_SIZE,
                                            (unsigned char *)sync_assistant, sync_assistant_len,
                                            sync_assistant_timestamp);
    // 使能AP电源
    uc_wiota_power_on();
#else
    // 使能同步助手电源
    uc_wiota_sync_assistant_power_on();
    rt_thread_mdelay(100);
    uc_wiota_sync_assistant_reboot();
    rt_thread_mdelay(500);

    // spi slaver 切换到同步助手
    wiota_spi_slaver_switch(SYNC_ASSISTANT_CHIP_INDEX);
    sync_res = wiota_flashing_by_chip_index(SYNC_ASSISTANT_CHIP_INDEX,
                                            CHIP_TYPE_UC8288,
                                            UC8288_FLASH_ID,
                                            UC8288_ERASE_SIZE,
                                            (unsigned char *)sync_assistant, sync_assistant_len,
                                            sync_assistant_timestamp);

    uc_wiota_sync_assistant_reboot();
    rt_thread_mdelay(500);
#endif

    return sync_res;
}

/**
 * @brief 刷机接口，主控通过SPI烧录AP和同步助手镜像
 *
 */
int wiota_flashing(void)
{
    int sync_res;
    int ap_res;
    int res;
    // res = 0 ap and sync flashing success,
    // res = 1 sync flashing fail,
    // res = 2 ap flashing fail,
    // res = 3 ap and sync flashing fail

    unsigned char work_mode = uc_static_get_gateway_auth_cfg()->work_mode;
    TRACE_I("work_mode %d", work_mode);

    switch (work_mode)
    {
    case UC_RF_TEST_MODE: // AP和同步助手的固件都刷为rf测试固件
        sync_res = wiota_flashing_sync_rf_test_bin();
        ap_res = wiota_flashing_ap_rf_test_bin();
        while (1) // 不在往下执行
        {
            rt_thread_mdelay(10000);
        }
        break;

    case UC_AP_RF_TEST_MODE: // 只刷AP的固件为rf测试固件
        sync_res = wiota_flashing_sync_normal_bin();
        ap_res = wiota_flashing_ap_rf_test_bin();
        while (1) // 不在往下执行
        {
            rt_thread_mdelay(10000);
        }
        break;

    case UC_SYNC_RF_TEST_MODE: // 只刷同步助手的固件为rf测试固件
        sync_res = wiota_flashing_sync_rf_test_bin();
        ap_res = wiota_flashing_ap_normal_bin();
        break;

    default: // 正常固件烧录
        sync_res = wiota_flashing_sync_normal_bin();
        ap_res = wiota_flashing_ap_normal_bin();
        break;
    }

    if (sync_res == 0 && ap_res == 0)
    {
        TRACE_I("flashing success");
        res = 0;
    }
    else if (sync_res != 0 && ap_res == 0)
    {
        TRACE_E("sync flashing fail");
        res = 1;
    }
    else if (sync_res == 0 && ap_res != 0)
    {
        TRACE_E("ap flashing fail");
        res = 2;
    }
    else
    {
        TRACE_E("ap and sync flashing fail");
        res = 3;
    }

    return res;
}
#ifdef FINSH_USING_MSH
MSH_CMD_EXPORT(wiota_flashing, flashing ap and sync assistant bin);
#endif